/**
 * 发布订阅模式：
 * 共存在3种角色，类比成我们平时关注某些微信公众号的操作 会有发布者、订阅者、发布中心
 * 发布者发布消息后交给发布中心，消息中心再去统一推送给订阅者
 */

// 发布中心
class PubSub {
  constructor() {
    // 一种类型的信息可能包含多个信息，比如{type1:[message1,message2],type2:[message2]}
    this.messages = {}
    // 一种类型下可能会有多个订阅者，比如，{type1:[listener,listener2]}
    this.subscribes = {}
  }
  // 添加发布类型信息
  publish (type, content) {
    if (!this.messages[type]) {
      this.messages[type] = []
    }
    this.messages[type].push(content)
    this.notify(type, content) // 在发布消息后通知订阅者  

  }
  // 添加订阅者
  subscribe (type, listenerCallback) {
    const messageType = this.subscribes[type]
    if (messageType) {
      messageType.push(listenerCallback)
    } else {
      this.subscribes[type] = [listenerCallback]
    }
  }
  // 发布中心进行通知
  notify (type, message) {
    this.subscribes[type].forEach(subscribe => {
      if (typeof subscribe === 'function') subscribe(message)
      else console.log('订阅者不是函数')
    })
  }
}

// 发布者
class Publisher {
  constructor(name, pub) {
    this.name = name
    this.pub = pub
  }
  publish (type, message) {
    this.pub.publish(type, message)
  }
}
// 订阅者
class Subscriber {
  constructor(name, pubsub) {
    this.name = name
    this.pubsub = pubsub
  }
  subscrib (type, cb) {
    // console.log('pubsub', this)
    this.pubsub.subscribe(type, cb)
  }
}

// 实例化
const pub = new PubSub()
const subscriber1 = new Subscriber('李四1', pub)
const subscriber2 = new Subscriber('李四2', pub)
const subscriber3 = new Subscriber('李四3', pub)
const publisher = new Publisher('张三', pub)



subscriber1.subscrib('news', (message) => {
  console.log(`${subscriber1.name}收到消息：${message}`)
})
subscriber2.subscrib('news', (message) => {
  console.log(`${subscriber2.name}收到消息${message}`)
})
subscriber3.subscrib('news', (message) => {
  console.log(`${subscriber2.name}收到消息${message}`)
})



publisher.publish('news', '今天天气不错')


subscriber1.subscrib('food', (food) => { console.log(`我是${subscriber1.name}，我收到的水果是${food}`) })
subscriber2.subscrib('food', (food) => { console.log(`我是${subscriber2.name}，我收到的水果是${food}`) })